package service

import (
	"errors"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"guns-go/global"
	"guns-go/model"
	"guns-go/model/request"
	"guns-go/model/response"
	"guns-go/utils"
	"strconv"
	"time"
)

func SaveSysNotice(notice *model.SysNotice, tx *gorm.DB) error {
	return tx.Create(notice).Error
}

func QuerySysNoticeById(noticeId int) (err error, notice *model.SysNotice) {
	var sysNotice *model.SysNotice
	err = global.GVA_DB.Where("id = ?", noticeId).Find(&sysNotice).Error
	return err, sysNotice
}

func UpdateSysNotice(notice *model.SysNotice, tx *gorm.DB) error {
	return tx.Model(&notice).Updates(notice).Error
}

func UpdateSysNoticeById(id int, status int8, tx *gorm.DB) error {
	return tx.Model(model.SysNotice{}).Where("id = ?", id).Update("status", status).Error
}

func SysNoticePage(sysNoticeParam *request.SysNoticeParam, c *gin.Context) (err error, result *response.PageResult) {

	var sysNoticeSlice []*model.SysNotice
	db := global.GVA_DB

	if sysNoticeParam != nil {

		//根据标题或内容模糊查询
		if sysNoticeParam.SearchValue != "" {
			db = db.Where("title like ?", "%"+sysNoticeParam.SearchValue+"%").
				Or("content like = ?", "%"+sysNoticeParam.SearchValue+"%")
		}

		//根据类型查询
		if sysNoticeParam.Type != nil {
			db = db.Where("type =  ?", sysNoticeParam.Type)
		}

		db = db.Where("status <> ?", 2)
	}

	var totalCount int64

	err = db.Find(&sysNoticeSlice).Count(&totalCount).Error

	if err != nil {
		return err, nil
	}

	pageNo, pageSize, db := utils.DefaultPage(c, db)

	err = db.Find(&sysNoticeSlice).Error

	if err != nil {
		return err, nil
	}

	return err, utils.CoverToPageResult(pageNo, pageSize, totalCount, sysNoticeSlice)
}

func SysNoticeAdd(sysNoticeParam *request.SysNoticeParam, c *gin.Context) error {

	err := checkParamByNotice(sysNoticeParam, true)
	if err != nil {
		return err
	}

	sysNotice := new(model.SysNotice)

	err = utils.SimpleCopyProperties(sysNotice, sysNoticeParam)

	if err != nil {
		return err
	}

	err, sysUser := GetUser(c)

	if err != nil {
		return err
	}

	sysNotice.PublicUserId = sysUser.Id
	sysNotice.PublicUserName = sysUser.Name

	err, sysEmp := QueryEmpById(sysUser.Id)

	if err != nil {
		return err
	}

	sysNotice.PublicOrgId = sysEmp.OrgId
	sysNotice.PublicOrgName = sysEmp.OrgName

	//如果是发布，则设置发布时间
	if *sysNotice.Status == 1 {
		sysNotice.PublicTime = time.Now()
	}

	tx := global.GVA_DB.Begin()

	err = SaveSysNotice(sysNotice, tx)

	if err != nil {
		tx.Rollback()
		return err
	}

	//通知到的人
	noticeUserIdList := sysNoticeParam.NoticeUserIdList
	//未读
	var noticeUserStatus int8
	noticeUserStatus = 0

	err = AddSysNoticeUser(sysNotice.Id, noticeUserIdList, noticeUserStatus, tx)
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func SysNoticeEdit(sysNoticeParam *request.SysNoticeParam) error {

	err, sysNotice := QuerySysNoticeById(sysNoticeParam.Id)

	if err != nil {
		return err
	}

	if sysNotice.Id == 0 {
		return errors.New("通知公告不存在")
	}

	//校验参数，检查状态是否正确
	err = checkParamByNotice(sysNoticeParam, true)
	if err != nil {
		return err
	}

	status := sysNotice.Status
	//非草稿状态
	if *status != 0 {
		return errors.New("编辑失败，通知公告非草稿状态时无法编辑")
	}

	err = utils.SimpleCopyProperties(sysNotice, sysNoticeParam)

	if err != nil {
		return err
	}

	//如果是发布，则设置发布时间
	if *status == 1 {
		sysNotice.PublicTime = time.Now()
	}

	tx := global.GVA_DB.Begin()

	err = UpdateSysNotice(sysNotice, tx)

	if err != nil {
		tx.Rollback()
		return err
	}

	//通知到的人
	noticeUserIdList := sysNoticeParam.NoticeUserIdList
	//未读
	var noticeUserStatus int8
	noticeUserStatus = 0

	err = EditSysNoticeUser(sysNotice.Id, noticeUserIdList, noticeUserStatus, tx)
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}
func SysNoticeDetail(sysNoticeParam *request.SysNoticeParam, c *gin.Context) (error, *response.SysNoticeDetailResult) {

	err, sysNotice := QuerySysNoticeById(sysNoticeParam.Id)

	if err != nil {
		return err, nil
	}

	if sysNotice.Id == 0 {
		return errors.New("通知公告不存在"), nil
	}

	id := sysNotice.Id

	//获取通知到的用户
	err, sysNoticeUserList := GetSysNoticeUserListByNoticeId(id)

	if err != nil {
		return err, nil
	}

	noticeUserIdList := make([]string, 0)

	noticeUserReadInfoList := make([]map[string]interface{}, 0)

	sysNoticeDetailResult := new(response.SysNoticeDetailResult)

	err = utils.SimpleCopyProperties(sysNoticeDetailResult, sysNotice)

	if err != nil {
		return err, nil
	}

	if len(sysNoticeUserList) > 0 {
		for _, sysNoticeUser := range sysNoticeUserList {
			//遍历通知到的用户，并构造
			noticeUserIdList = append(noticeUserIdList, strconv.Itoa(sysNoticeUser.UserId))
			dict := make(map[string]interface{}, 0)

			dict["userId"] = sysNoticeUser.UserId

			err, sysUser := GetUser(c)

			if err != nil {
				return err, nil
			}

			dict["userName"] = sysUser.Name
			dict["readStatus"] = sysNoticeUser.UserId
			dict["readTime"] = sysNoticeUser.UserId

			noticeUserReadInfoList = append(noticeUserReadInfoList, dict)
		}
	}

	sysNoticeDetailResult.NoticeUserIdList = noticeUserIdList
	sysNoticeDetailResult.NoticeUserReadInfoList = noticeUserReadInfoList

	//如果该条通知公告为已发布，则将当前用户的该条通知公告设置为已读
	if *sysNotice.Status == 1 {
		err = Read(sysNotice.Id, 11, 1)

		if err != nil {
			return err, nil
		}
	}
	return err, sysNoticeDetailResult
}

func SysNoticeDelete(sysNoticeParam *request.SysNoticeParam) error {

	err, sysNotice := QuerySysNoticeById(sysNoticeParam.Id)

	if err != nil {
		return err
	}

	if sysNotice.Id == 0 {
		return errors.New("通知公告不存在")
	}

	status := sysNotice.Status

	if *status != 0 && *status != 2 {
		return errors.New("删除失败，通知公告已发布或已删除")
	}

	tx := global.GVA_DB.Begin()
	err = UpdateSysNoticeById(sysNotice.Id, 2, tx)

	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func SysNoticeChangeStatus(sysNoticeParam *request.SysNoticeParam) error {

	err, sysNotice := QuerySysNoticeById(sysNoticeParam.Id)

	if err != nil {
		return err
	}

	//校验参数，检查状态是否正确
	err = checkParamByNotice(sysNoticeParam, false)
	if err != nil {
		return err
	}

	sysNotice.Status = sysNoticeParam.Status

	//如果是撤回，则设置撤回时间
	if *sysNotice.Status == 2 {
		sysNotice.CancelTime = time.Now()
	} else if *sysNotice.Status == 1 {
		//如果是发布，则设置发布时间
		sysNotice.PublicTime = time.Now()
	}
	tx := global.GVA_DB.Begin()
	err = UpdateSysNotice(sysNotice, tx)

	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func SysNoticeReceived(sysNoticeParam *request.SysNoticeParam, c *gin.Context) (error, *response.PageResult) {

	var r []*response.SysNoticeReceiveResult
	table := global.GVA_DB.Select("sys_notice.*,sys_notice_user.status as read_status, sys_notice_user.read_time").
		Table("sys_notice").
		Joins("left join sys_notice_user on sys_notice.id = sys_notice_user.notice_id")

	//查询当前用户的
	err, sysUser := GetUser(c)

	if err != nil {
		return err, nil
	}

	table = table.Where("sys_notice_user.user_id = ?", sysUser.Id)

	if sysNoticeParam != nil {
		//根据标题或内容模糊查询
		if sysNoticeParam.SearchValue != "" {
			table = table.Where("sys_notice.title like ?", "%"+sysNoticeParam.SearchValue+"%").
				Or("sys_notice.content like ?", "%"+sysNoticeParam.SearchValue+"%")
		}

		//根据类型查询
		if sysNoticeParam.Type != nil {
			table = table.Where("sys_notice.type = ?", sysNoticeParam.Type)
		}
	}

	//查询未删除的
	table = table.Where("sys_notice.status <> ?", 2)

	var totalCount int64

	err = table.Count(&totalCount).Error

	if err != nil {
		return err, nil
	}

	pageNo, pageSize, table := utils.DefaultPage(c, table)

	err = table.Scan(&r).Error

	if err != nil {
		return err, nil
	}

	return err, utils.CoverToPageResult(pageNo, pageSize, totalCount, r)
}

//校验参数，是否有重复的名称和编码
func checkParamByNotice(sysNoticeParam *request.SysNoticeParam, isAddOrEdit bool) error {

	//保存或编辑时，传递的状态参数应为草稿，或发布
	status := sysNoticeParam.Status

	if isAddOrEdit {
		if status != nil && *status != 0 && *status != 1 {
			return errors.New("状态格式错误，请检查status参数")
		}
	} else {
		//修改状态时，传递的状态参数应为撤回或删除或发布
		if status != nil && *status != 1 && *status != 2 && *status != 3 {
			return errors.New("状态格式错误，请检查status参数")
		}
	}
	return nil
}
